#include "BondColDelegate.h"

#include <bondlib/BondCalendar.h>
#include <bondlib/BondContainer.h>
#include <core/ImageMgr.h>
#include <core/StyleMgr.h>
#include <qbbond/QbBondDefines.h>
#include <widgets/table/STableColumnSet.h>

#include <QApplication>
#include <QDate>
#include <QEvent>
#include <QFont>
#include <QFontMetrics>
#include <QHeaderView>
#include <QItemDelegate>
#include <QMouseEvent>
#include <QPoint>
#include <QStylePainter>
#include <QTableView>

#include "widgets/table/STable.h"

RemainDateDelegate::RemainDateDelegate(QObject* parent, STableColumnSet* colSet,
                                       calendarShowType showType)
    : DefaulTableItemDelegate(parent), m_showType(showType) {
  m_table = static_cast<SVirtualTable*>(parent);
  m_table->table()->setMouseTracking(true);
  m_table->table()->viewport()->installEventFilter(this);
  connect(colSet, &STableColumnSet::clearHolidayMap, this,
          &RemainDateDelegate::onClearHolidayRect);
  connect(m_table, &SVirtualTable::viewPosChanged, this,
          &RemainDateDelegate::onClearHolidayRect);
}

void RemainDateDelegate::paint(QPainter* painter,
                               const QStyleOptionViewItem& option,
                               const QModelIndex& index) const {
  DefaulTableItemDelegate::paint(painter, option, index);

  QString strKey = index.data(DataIdRole).toString();
  QString strHolidayDays = index.data(HolidayNumberRole).toString();

  int holidayType = index.data(HolidayTypeRole).toInt();

  QString remainDate = index.data(Qt::DisplayRole).toString();  // 剩余期限
  QFontMetrics fontMetrics(option.font);
  int remainDatelen = fontMetrics.width(remainDate) + 1;  // 剩余期限长度

  QRect r = option.rect;
  int imgX = 4 + remainDatelen * 1.2 + 3 + r.x();
  r.setLeft(imgX);

  QRect rcHoliday;
  if (holidayType != holidayNull) {
    int nXiuWidth = 0;
    int nXiuValWidth = 0;
    if (holidayType == holidayCib) {
      nXiuWidth = ImgMgr::instance().image("widgets_cell_xiu_cib")->width();
      nXiuValWidth =
          ImgMgr::instance().image("widgets_cell_xiu_cib_number")->width();
    } else {
      nXiuWidth = ImgMgr::instance().image("widgets_cell_xiu_sse")->width();
      nXiuValWidth =
          ImgMgr::instance().image("widgets_cell_xiu_sse_number")->width();
    }
    int holidayWidth = nXiuWidth;
    holidayWidth += qMax(
        option.fontMetrics.horizontalAdvance(strHolidayDays) + 1, nXiuValWidth);
    int top = r.center().y() -
              ImgMgr::instance().image("widgets_cell_xiu_cib")->height() / 2 +
              1;
    rcHoliday.setRect(
        r.left(), top, holidayWidth,
        ImgMgr::instance().image("widgets_cell_xiu_cib")->height());
    if (m_holidayRectMap.find(strKey) != m_holidayRectMap.end())
      m_holidayRectMap.erase(strKey);
    m_holidayRectMap.insert({strKey, rcHoliday});
  }
  if (holidayType != holidayNull) {
    int left = rcHoliday.left();
    SImage* img = ImgMgr::instance().image(holidayType == holidayCib
                                               ? "widgets_cell_xiu_cib"
                                               : "widgets_cell_xiu_sse");
    painter->drawImage(left, rcHoliday.top(), *img);
    left += img->width();

    img = ImgMgr::instance().image(holidayType == holidayCib
                                       ? "widgets_cell_xiu_cib_number"
                                       : "widgets_cell_xiu_sse_number");
    QRect r(left, rcHoliday.top(), rcHoliday.right() - left,
            rcHoliday.height());
    painter->drawImage(r, *img);
    painter->save();
    painter->setPen(Qt::black);
    QFont f = option.font;
    f.setPixelSize(10);
    painter->setFont(f);
    painter->drawText(QRect(left, rcHoliday.top(), rcHoliday.right() - left,
                            rcHoliday.height()),
                      strHolidayDays, QTextOption(Qt::AlignCenter));
    painter->restore();
  }
}

QSize RemainDateDelegate::sizeHint(const QStyleOptionViewItem& option,
                                   const QModelIndex& index) const {
  return DefaulTableItemDelegate::sizeHint(option, index);
}

bool RemainDateDelegate::eventFilter(QObject* object, QEvent* event) {
  if (event->type() == QEvent::MouseMove) {
    QMouseEvent* me = static_cast<QMouseEvent*>(event);
    bool isInHolidayImg = false;
    for (auto r : m_holidayRectMap) {
      if (r.second.contains(
              m_table->table()->viewport()->mapFromGlobal(QCursor::pos()))) {
        QModelIndex index = m_table->table()->indexAt(me->pos());
        if (index.isValid()) {
          QString maturityDay =
              QString::number(index.data(MaturityDayRole).toInt());
          QDate md = QDate::fromString(maturityDay, "yyyyMMdd");
          if (!m_tipCalendar) {
            m_tipCalendar.reset(new SCalendar(
                nullptr, true,
                tr("关于国务院未发布放假通知的年份，我司将按经\r\n验维护后2年的"
                   "节假日，2年以外的仅考虑周末双\r\n休，仅供参考")));
            m_tipCalendar->setFixedSize(264, 290);
          }
          if (!m_tipCalendar->isVisible()) {
            QPoint p = QCursor::pos();
            if (m_showType == TopOrBottomCursor) {
              QRect screenRect = QApplication::desktop()->screenGeometry();
              if (p.x() + 10 + m_tipCalendar->width() > screenRect.width() ||
                  p.y() + 10 + m_tipCalendar->height() > screenRect.height()) {
                m_tipCalendar->setGeometry(
                    p.x() + 10, p.y() - m_tipCalendar->height() - 10,
                    m_tipCalendar->width(), m_tipCalendar->height());
              } else {
                m_tipCalendar->setGeometry(p.x() + 10, p.y() + 10,
                                           m_tipCalendar->width(),
                                           m_tipCalendar->height());
              }
            } else if (m_showType) {
              m_tipCalendar->setGeometry(p.x() + 10, p.y() + 10,
                                         m_tipCalendar->width(),
                                         m_tipCalendar->height());
            } else {
              int x = p.x() + 10;
              int y = p.y() - m_tipCalendar->height() - 10;
              m_tipCalendar->setGeometry(x, y, m_tipCalendar->width(),
                                         m_tipCalendar->height());
            }
            m_tipCalendar->setSelectedDate(md);
            m_tipCalendar->setStart(md);
            m_tipCalendar->setEnd(md);
          }
          m_tipCalendar->show();
          isInHolidayImg = true;
        }
        break;
      }
    }
    if (!isInHolidayImg && m_tipCalendar) {
      m_tipCalendar->hide();
    }
  } else if ((event->type() == QEvent::WindowDeactivate) ||
             (event->type() == QEvent::Hide)) {
    if (m_tipCalendar) m_tipCalendar->hide();
  }
  return DefaulTableItemDelegate::eventFilter(object, event);
}

void RemainDateDelegate::onClearHolidayRect() { m_holidayRectMap.clear(); }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

BrokerCorpDelegate::BrokerCorpDelegate(QObject* parent)
    : DefaulTableItemDelegate(parent) {}

void BrokerCorpDelegate::paint(QPainter* painter,
                               const QStyleOptionViewItem& option,
                               const QModelIndex& index) const {
  DefaulTableItemDelegate::paint(painter, option, index);

  const QRect& r = option.rect;
  const int width = 36;
  const int height = 18;

  QRect rcBroker(r);
  rcBroker.setHeight(height);
  rcBroker.moveCenter({rcBroker.center().x(), r.center().y()});

  int align = index.data(DataAlignRole).toInt();
  if (align == Qt::AlignCenter) {
    rcBroker.setLeft(rcBroker.left() + 3);
    rcBroker.setWidth(qMin(width, r.width() - 6));
  } else if (align == Qt::AlignRight) {
    rcBroker.setLeft(rcBroker.right() - qMin(width, r.width() - 6));
  } else {
    rcBroker.setLeft(rcBroker.left() + 3);
    rcBroker.setWidth(qMin(width, r.width() - 6));
  }

  QString strBroker;
  QColor clrBroker;
  QColor clrText = StyleMgr::instance().color("TextNormal");
  QFont f = painter->font();

  int nBroker = index.data(BrokerIdRole).toInt();
  switch (nBroker) {
    case 1:
      clrBroker = StyleMgr::instance().color("BrokerTP");
      strBroker = tr("国利");
      break;
    case 2:
      clrBroker = StyleMgr::instance().color("BrokerICAP");
      strBroker = tr("国际");
      break;
    case 3:
      clrBroker = StyleMgr::instance().color("BrokerBGC");
      strBroker = tr("中诚");
      break;
    case 4:
      clrBroker = StyleMgr::instance().color("BrokerPA");
      strBroker = tr("平安");
      break;
    case 5:
      clrBroker = StyleMgr::instance().color("BrokerXT");
      strBroker = tr("信唐");
      break;
    case 6:
      clrBroker = StyleMgr::instance().color("BrokerUEDA");
      strBroker = tr("上田");
      clrText = Qt::black;
      break;
    case 98:
      clrBroker = StyleMgr::instance().color("BrokerSS");
      strBroker = tr("森浦");
      break;
    case 99:
      clrText = clrBroker = StyleMgr::instance().color("BrokerBestText");
      strBroker = tr("最优");
      break;
    case 110: {
      const int SHFI_QUOTETYPE = index.data(DataIdRole).toInt();
      if (0 == SHFI_QUOTETYPE) {
        strBroker = tr("上证固收");
        f.setPixelSize(9);
        clrText = clrBroker = QColor(198, 83, 45);
      } else {
        strBroker = QString("%1").arg(SHFI_QUOTETYPE);  // treat as seqNo.
        // clrText = TextNormal;
        clrBroker = Qt::transparent;
      }

    } break;
    case 111: {
      clrText = clrBroker = QColor(186, 103, 82);
      strBroker = tr("交易所");
      f.setPixelSize(10);
    } break;
    case 112 /*MARKET_CFETS*/: {
      clrText = clrBroker = QColor(59, 135, 120);
      const int CFETS_QUOTETYPE = index.data(DataIdRole).toInt();
      strBroker =
          (CFETS_QUOTETYPE == CCFETSQuote::XBOND) ? "X-Bond" : tr("双边报价");
      f.setPixelSize((CFETS_QUOTETYPE == CCFETSQuote::XBOND)
                         ? 10
                         : 9);  // 建议根据rcBroker的宽度计算得到字体高度
    } break;
    default:
      return;
  }

  painter->setPen(Qt::NoPen);
  if ((99 == nBroker) || (nBroker > 99)) {
    painter->setPen(QPen(clrBroker));
  } else {
    painter->setBrush(QBrush(clrBroker));
  }

  painter->drawRoundedRect(rcBroker, 2, 2);
  painter->setBrush(Qt::NoBrush);

  painter->setPen(clrText);
  painter->setFont(f);
  painter->drawText(rcBroker, strBroker,
                    QTextOption(Qt::AlignCenter | Qt::AlignVCenter));
  painter->setPen(Qt::NoPen);
}

QSize BrokerCorpDelegate::sizeHint(const QStyleOptionViewItem& option,
                                   const QModelIndex& index) const {
  return DefaulTableItemDelegate::sizeHint(option, index);
}

void ExchangeSeqNoDelegate::paint(QPainter* painter,
                                  const QStyleOptionViewItem& option,
                                  const QModelIndex& index) const {
  DefaulTableItemDelegate::paint(painter, option, index);
  const QString& SeqNo = index.data(Qt::DisplayRole).toString();
  if (SeqNo.isEmpty()) return;

  const QColor& clrText = index.data(Qt::ForegroundRole).value<QColor>();
  const QColor& clrBackground = index.data(PostfixTxtRectColor).value<QColor>();
  const int& align = index.data(Qt::TextAlignmentRole).toInt();
  const QFont& fnt = index.data(Qt::FontRole).value<QFont>();

  const QRect& r = option.rect;

  QRect rcSeqNo;
  rcSeqNo.setTop(r.top() + 1);
  rcSeqNo.setBottom(r.bottom() - 1);

  const QFontMetrics f(fnt);
  const int& txtWidth = f.horizontalAdvance(SeqNo);
  rcSeqNo.setWidth(txtWidth + 4);

  if (align & Qt::AlignLeft) {
    rcSeqNo.moveLeft(r.left());
  } else if (align & Qt::AlignRight) {
    rcSeqNo.moveRight(r.right());
  } else if (align & Qt::AlignHCenter) {
    rcSeqNo.moveCenter({r.center().x(), rcSeqNo.center().y()});
  }

  if (align & Qt::AlignTop) {
    rcSeqNo.moveLeft(r.left());
  } else if (align & Qt::AlignBottom) {
    rcSeqNo.moveRight(r.right());
  } else if (align & Qt::AlignVCenter) {
    rcSeqNo.moveCenter({rcSeqNo.center().x(), r.center().y()});
  }

  painter->setPen(clrText);
  painter->fillRect(rcSeqNo, clrBackground);
  painter->setFont(fnt);
  painter->drawText(rcSeqNo, SeqNo, QTextOption(Qt::AlignCenter));
}
